package com.ruoyi.system.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.order.domain.*;
import com.ruoyi.system.order.mapper.*;
import com.ruoyi.system.order.service.OrderService;
import com.ruoyi.system.order.vo.DishSummary;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务实现 —— 完全对应前端搜索字段，Java 8 语法
 */
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderBasicMapper orderBasicMapper;
    private final UserInfoMapper  userInfoMapper;
    private final MerchantMapper  merchantMapper;
    private final RiderMapper     riderMapper;
    private final DishMapper      dishMapper;

    // ======================== ① 分页查询 ========================
    @Override
    public Page<OrderDetailDTO> pageQuery(OrderQueryParams qp) {

        //Page<OrderBasic> page = new Page<>(qp.getPageNum(), qp.getPageSize());
        QueryWrapper<OrderBasic> qw = new QueryWrapper<>();

        /* ================= 主表字段 ================= */
        if (StrUtil.isNotBlank(qp.getOrderNo())) {
            qw.like("order_no", qp.getOrderNo());
        }
        if (StrUtil.isNotBlank(qp.getDeliveryStatus())) {
            qw.eq("delivery_status", qp.getDeliveryStatus());
        }
        if (StrUtil.isNotBlank(qp.getExceptionStatus())) {
            qw.eq("exception_status", qp.getExceptionStatus());
        }
        /* ★★★ 新增：只查异常订单 ★★★ */
        if (Boolean.TRUE.equals(qp.getIsException())) {
            qw.eq("is_exception", 1);   // 直接命中索引，速度飞起
        }
        // 创建时间范围
        addTimeRange(qw, qp.getCreateTime());

        /* ================ 跨表条件 ================ */

        // ① 菜品名称 → order_id
        if (StrUtil.isNotBlank(qp.getDishName())) {
            List<Long> orderIds = dishMapper.selectList(
                    new QueryWrapper<Dish>()
                            .select("DISTINCT order_id")
                            .like("name", qp.getDishName())
            ).stream().map(Dish::getOrderId).collect(Collectors.toList());

            if (CollUtil.isEmpty(orderIds)) {
                return emptyPage(qp);   // 提前 short‑circuit
            }
            qw.in("id", orderIds);
        }

        // ② 商家名称 → merchant_id
        if (StrUtil.isNotBlank(qp.getMerchantName())) {
            List<Long> mIds = merchantMapper.selectList(
                    new QueryWrapper<Merchant>()
                            .select("id")
                            .like("name", qp.getMerchantName())
            ).stream().map(Merchant::getId).collect(Collectors.toList());

            if (CollUtil.isEmpty(mIds)) {
                return emptyPage(qp);
            }
            qw.in("merchant_id", mIds);
        }

        // ③ 买家昵称 → user_id
        if (StrUtil.isNotBlank(qp.getUserName())) {
            List<Long> uIds = userInfoMapper.selectList(
                    new QueryWrapper<UserInfo>()
                            .select("id")
                            .like("nickname", qp.getUserName())
            ).stream().map(UserInfo::getId).collect(Collectors.toList());

            if (CollUtil.isEmpty(uIds)) {
                return emptyPage(qp);
            }
            qw.in("user_id", uIds);
        }

        // ④ 配送员姓名 → rider_id
        if (StrUtil.isNotBlank(qp.getRiderName())) {
            List<Long> rIds = riderMapper.selectList(
                    new QueryWrapper<Rider>()
                            .select("rider_id")
                            .like("name", qp.getRiderName())
            ).stream().map(Rider::getRiderId).collect(Collectors.toList());

            if (CollUtil.isEmpty(rIds)) {
                return emptyPage(qp);
            }
            qw.in("rider_id", rIds);
        }

        // ⑤ 手机号：买家 / 商家 / 配送员
        if (StrUtil.isNotBlank(qp.getPhone())) {
            List<Long> uIds = userInfoMapper.selectList(
                    new QueryWrapper<UserInfo>().select("id").like("phone", qp.getPhone())
            ).stream().map(UserInfo::getId).collect(Collectors.toList());

            List<Long> mIds = merchantMapper.selectList(
                    new QueryWrapper<Merchant>().select("id").like("phone", qp.getPhone())
            ).stream().map(Merchant::getId).collect(Collectors.toList());

            List<Long> rIds = riderMapper.selectList(
                    new QueryWrapper<Rider>().select("rider_id").like("phone", qp.getPhone())
            ).stream().map(Rider::getRiderId).collect(Collectors.toList());

            // 三者皆空 → 直接返回空页
            if (CollUtil.isEmpty(uIds) && CollUtil.isEmpty(mIds) && CollUtil.isEmpty(rIds)) {
                return emptyPage(qp);
            }
            qw.and(wrapper -> {
                if (CollUtil.isNotEmpty(uIds)) {
                    wrapper.in("user_id", uIds);
                }
                if (CollUtil.isNotEmpty(rIds)) {
                    wrapper.or().in("rider_id", rIds);
                }
                if (CollUtil.isNotEmpty(mIds)) {
                    wrapper.or().in("merchant_id", mIds);
                }
            });
        }

//        /* ================ 执行分页 ================ */
//        //Page<OrderBasic> resultPage = orderBasicMapper.selectPage(page, qw);
//
////        if (resultPage.getRecords().isEmpty()) {
////            return emptyPage(qp);
////        }
//
//        /* ================ 组装 DTO ================ */
//        List<OrderDetailDTO> dtoList = buildDTO(resultPage.getRecords());
//
//        // MyBatis‑Plus Page<T>.convert()
//        Page<OrderDetailDTO> pageResult = (Page<OrderDetailDTO>) resultPage.convert(ob ->
//                dtoList.stream()
//                        .filter(d -> d.getOrderBasic().getId().equals(ob.getId()))
//                        .findFirst()
//                        .orElse(null)
//        );
//        // 关键：手动设置 total
//        pageResult.setTotal(resultPage.getTotal());
//        System.out.println("查到的总数：" + resultPage.getTotal());
//        return pageResult;

        PageHelper.startPage(qp.getPageNum(), qp.getPageSize());

        // 调用Mapper，不传Page参数，返回List
        List<OrderBasic> list = orderBasicMapper.selectList(qw);

        // 用PageInfo包装分页结果
        PageInfo<OrderBasic> pageInfo = new PageInfo<>(list);

        // 组装DTO
        List<OrderDetailDTO> dtoList = buildDTO(list);

        // 返回MyBatis-Plus的Page，方便兼容前端
        Page<OrderDetailDTO> pageResult = new Page<>();
        pageResult.setCurrent(pageInfo.getPageNum());
        pageResult.setSize(pageInfo.getPageSize());
        pageResult.setTotal(pageInfo.getTotal());
        pageResult.setRecords(dtoList);

        System.out.println("查到的总数：" + pageInfo.getTotal());

        return pageResult;

    }
    /** 把主表记录批量转成 DTO，可复用你之前的实现 */
    private List<OrderDetailDTO> buildDTO(List<OrderBasic> basics) {
        List<OrderDetailDTO> list = new ArrayList<>();
        for (OrderBasic ob : basics) {
            OrderDetailDTO dto = new OrderDetailDTO();
            dto.setOrderBasic(ob);

            // 查询用户
            UserInfo user = ob.getUserId() != null ? userInfoMapper.selectById(ob.getUserId()) : null;
            dto.setUserInfo(user);

            // 查询商家
            Merchant merchant = merchantMapper.selectById(ob.getMerchantId());
            dto.setMerchant(merchant);

            // 查询骑手
            Rider rider = ob.getRiderId() != null ? riderMapper.selectById(ob.getRiderId()) : null;
            dto.setRider(rider);

            // 查询菜品
            List<Dish> dishes = dishMapper.selectList(new QueryWrapper<Dish>().eq("order_id", ob.getId()));
            dto.setDishes(mergeSame(dishes)); // mergeSame 是你已有的工具方法

            list.add(dto);
        }
        return list;
    }
    private void addTimeRange(QueryWrapper<OrderBasic> qw, String flag) {
        if (StrUtil.isBlank(flag)) return;

        LocalDateTime start, end;
        LocalDateTime now = LocalDateTime.now();

        switch (flag) {
            case "this_month":
                start = now.withDayOfMonth(1).with(LocalTime.MIN);
                end   = now.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
                break;

            case "last_3_months":
                start = now.minusMonths(3).with(LocalTime.MIN);
                end   = now.with(LocalTime.MAX);
                break;

            case "this_year":
                start = now.withDayOfYear(1).with(LocalTime.MIN);
                end   = now.withMonth(12).withDayOfMonth(31).with(LocalTime.MAX);
                break;

            case "2024":
            case "2023":
                int year = Integer.parseInt(flag);
                start = LocalDate.of(year, 1, 1).atStartOfDay();
                end   = LocalDate.of(year, 12, 31).atTime(LocalTime.MAX);
                break;

            case "before_2023":
                qw.lt("order_time", LocalDate.of(2023, 1, 1).atStartOfDay());
                return;

            default:
                return;
        }

        qw.between("order_time", start, end);
    }


    // ======================== ② 单条详情 ========================
    @Override
    public OrderDetailDTO getDetail(Long orderId) {
        OrderBasic ob = orderBasicMapper.selectById(orderId);
        if (ob == null) return null;

        UserInfo user = ob.getUserId() == null ? null : userInfoMapper.selectById(ob.getUserId());
        Merchant merchant = merchantMapper.selectById(ob.getMerchantId());
        Rider rider = ob.getRiderId() == null ? null : riderMapper.selectById(ob.getRiderId());

        List<Dish> dishes = dishMapper.selectList(new QueryWrapper<Dish>().eq("order_id", orderId));

        OrderDetailDTO dto = new OrderDetailDTO();
        dto.setOrderBasic(ob);
        dto.setUserInfo(user);
        dto.setMerchant(merchant);
        dto.setRider(rider);
        dto.setDishes(mergeSame(dishes));
        return dto;
    }

    // ======================== ③ 辅助方法 ========================
    /** 将前端状态字符串转成数据库 delivery_status 编码 */
    private Integer toStatusCode(String s) {
        if (!notBlank(s)) return null;
        if ("waiting_rider".equals(s))  return 1;
        if ("delivering".equals(s))     return 2;
        if ("delivered".equals(s))      return 3;
        if ("timeout".equals(s))        return 4;
        if ("pending_refund".equals(s)) return 5;
        if ("refuse_refund".equals(s))  return 6;
        if ("refund_success".equals(s)) return 7;
        if ("success".equals(s))        return 8;
        if ("closed".equals(s))         return 9;
        return null;
    }

    /** 创建时间范围映射 */

    private List<OrderDetailDTO> convertToDetailDTO(List<OrderBasic> records) {
        // 这里根据你的业务需要封装转换逻辑
        return records.stream().map(order -> {
            OrderDetailDTO dto = new OrderDetailDTO();
            BeanUtils.copyProperties(order, dto);
            return dto;
        }).collect(Collectors.toList());
    }

    /** 组装 List<OrderBasic> → List<OrderDetailDTO> */
    private List<OrderDetailDTO> assembleDetails(List<OrderBasic> orders) {
        List<Long> orderIds = orders.stream().map(OrderBasic::getId).collect(Collectors.toList());

        Map<Long, List<Dish>> dishMap = dishMapper.selectList(
                        new QueryWrapper<Dish>().in("order_id", orderIds))
                .stream().collect(Collectors.groupingBy(Dish::getOrderId));

        Set<Long> userIds = orders.stream().map(OrderBasic::getUserId).filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, UserInfo> userMap = userIds.isEmpty() ? Collections.<Long, UserInfo>emptyMap() :
                userInfoMapper.selectBatchIds(userIds).stream()
                        .collect(Collectors.toMap(UserInfo::getId, u -> u));

        Set<Long> merchantIds = orders.stream().map(OrderBasic::getMerchantId).collect(Collectors.toSet());
        Map<Long, Merchant> merchantMap = merchantMapper.selectBatchIds(merchantIds).stream()
                .collect(Collectors.toMap(Merchant::getId, m -> m));

        Set<Long> riderIds = orders.stream().map(OrderBasic::getRiderId).filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, Rider> riderMap = riderIds.isEmpty() ? Collections.<Long, Rider>emptyMap() :
                riderMapper.selectBatchIds(riderIds).stream()
                        .collect(Collectors.toMap(Rider::getRiderId, r -> r));

        List<OrderDetailDTO> list = new ArrayList<>();
        for (OrderBasic ob : orders) {
            OrderDetailDTO dto = new OrderDetailDTO();
            dto.setOrderBasic(ob);
            dto.setDishes(mergeSame(dishMap.getOrDefault(ob.getId(), Collections.<Dish>emptyList())));
            dto.setUserInfo(userMap.get(ob.getUserId()));
            dto.setMerchant(merchantMap.get(ob.getMerchantId()));
            dto.setRider(riderMap.get(ob.getRiderId()));
            list.add(dto);
        }
        return list;
    }

    /** 合并同菜品行 */
    private List<DishSummary> mergeSame(List<Dish> raw) {
        Map<String, DishSummary> map = new LinkedHashMap<>();
        for (Dish d : raw) {
            String key = d.getName() + "#" + d.getSpec() + "#" + d.getSpiciness();
            DishSummary s = map.get(key);
            if (s == null) {
                s = new DishSummary();
                s.setName(d.getName());
                s.setSpec(d.getSpec());
                s.setSpiciness(d.getSpiciness());
                s.setPrice(d.getPrice());
                s.setImageUrl(d.getImageUrl());
                s.setQuantity(1);
                map.put(key, s);
            } else {
                s.setQuantity(s.getQuantity() + 1);
            }
        }
        return new ArrayList<>(map.values());
    }

    private boolean notBlank(String str) {
        return str != null && str.trim().length() > 0;
    }

    private Page<OrderDetailDTO> emptyPage(OrderQueryParams qp) {
        return new Page<>(qp.getPageNum(), qp.getPageSize(), 0);
    }
}
